package com.mask.encryption.web;

import com.mask.encryption.config.MaskEncryptionWebProperties;
import com.mask.encryption.service.MaskEncryptionService;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;

@ControllerAdvice
public class MaskDecryptRequestBodyAdvice extends RequestBodyAdviceAdapter {

    private final MaskEncryptionService encryptionService;
    private final MaskEncryptionWebProperties webProps;
    private final HttpServletRequest request;
    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    public MaskDecryptRequestBodyAdvice(MaskEncryptionService encryptionService,
                                        MaskEncryptionWebProperties webProps,
                                        HttpServletRequest request) {
        this.encryptionService = encryptionService;
        this.webProps = webProps;
        this.request = request;
    }

    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        if (!webProps.isEnabled() || !webProps.isDecryptRequest()) {
            return false;
        }
        String uri = request.getRequestURI();
        for (String pattern : webProps.getIgnorePaths()) {
            if (pathMatcher.match(pattern, uri)) {
                return false;
            }
        }
        if (webProps.isRequireHeader()) {
            String hv = request.getHeader(webProps.getHeaderToggle());
            if (hv == null || hv.isEmpty()) {
                return false;
            }
        }
        MediaType contentType = MediaType.parseMediaType(request.getContentType() == null ? MediaType.APPLICATION_JSON_VALUE : request.getContentType());
        return MediaType.APPLICATION_JSON.includes(contentType);
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> selectedConverterType) throws IOException {
        byte[] bodyBytes = StreamUtils.copyToByteArray(inputMessage.getBody());
        if (bodyBytes.length == 0) {
            return inputMessage;
        }
        // 前端传来 Base64 密文
        String base64Cipher = new String(bodyBytes, StandardCharsets.UTF_8).trim();
        String jsonPlain = encryptionService.decryptFromBase64(base64Cipher);
        byte[] jsonBytes = jsonPlain.getBytes(StandardCharsets.UTF_8);
        return new HttpInputMessage() {
            @Override
            public InputStream getBody() {
                return new ByteArrayInputStream(jsonBytes);
            }

            @Override
            public HttpHeaders getHeaders() {
                return inputMessage.getHeaders();
            }
        };
    }
}


